

package example.hello;

import java.awt.Button;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import com.ibm.aglet.Aglet;
import com.ibm.aglet.AgletProxy;
import com.ibm.aglet.Message;
import com.ibm.aglet.util.AddressChooser;
import com.ibm.agletx.util.SimpleItinerary;


public class HelloAglet extends Aglet {

    /*
     * UI to interact with a user
     * this will be automatically disposed when the aglet is disposed
     */
    transient Frame my_dialog = null;  // not serialized

    /*
     * message
     */
    String message = null;

    /*
     * home address represented as a string
     */
    String home = null;

    /*
     * Itinerary
     */
    SimpleItinerary itinerary = null;

    /*
     * Initializes the aglet. 
     * Only called the very first time this aglet is created. 
     */
    public void onCreation(Object init) {
        setMessage("Hello World!");  //default message

        // Create GUI to control this Aglet
        createGUI();
        itinerary = new SimpleItinerary(this);

        // Initialize the variable.
        home = getAgletContext().getHostingURL().toString();
    }
    
    protected void createGUI(){
        my_dialog = new MyDialog(this);

        my_dialog.pack();
        my_dialog.setSize(my_dialog.getPreferredSize());
        my_dialog.setVisible(true);
    }

    /*
    * Set the message
    * @param message the message to send
    */
    public void setMessage(String message){
        this.message = message;
    }

    /*
     * Handles the message
     * @param msg the message sent
     */
    public boolean handleMessage(Message msg) {
        if (msg.sameKind("atHome")) {
            atHome(msg);
        } else if (msg.sameKind("startTrip")) {
            startTrip(msg);
        } else if (msg.sameKind("sayHello")) {
            sayHello(msg);
        } else if (msg.sameKind("dialog")) {
            dialog(msg);
        } else {
            return false;
        }
        return true;
    }

    /*
     * Reports arrival home and disappears
     */
    public void atHome(Message msg) {
        setText("I'm back.");  // greetings
        waitMessage(2 * 1000); // show message, 2 seconds
        dispose();             // dispose it self
    }

    /**
     * Strats the trip of this aglet to the destination.
     */
    public synchronized void startTrip(Message msg) {
        // get the address for trip
        String destination = (String)msg.getArg();
        
        // Go to the destination and Send "sayHello" message to owner(this)
        try {
            itinerary.go(destination, "sayHello");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /*
     * Say hello!
     */
    public void sayHello(Message msg) {
        setText(message);        // greetings
        waitMessage(5 * 1000);   // show message, 5 seconds

        // try back home
        try {
            setText("I'll go back to.. " + home);
            waitMessage(1000);  // 1 second
            // Go back home and Send "atHome" message to owner this
            itinerary.go(home, "atHome");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /**
     * Creates and shows the dialog window. 
     * This aglet keeps the reference to the instance
     * of the Dialog to avoid opening multiple dialog windows.
     */
    public void dialog(Message msg) {
        // check and create a dialog box
        if (my_dialog == null) {
            my_dialog = new MyDialog(this);
            my_dialog.pack();
            my_dialog.setSize(my_dialog.getPreferredSize());
        }
        
        // show the dialog box
        my_dialog.setVisible(true);
    }
}


/*
 * MyDialog class is the window to be opened when the dialog required.
 * This is NOT a subclass of Dialog.
 */
class MyDialog extends Frame implements WindowListener, ActionListener{

    /*
     * The aglet a user interacts with.
     */
    private HelloAglet aglet  = null;

    /*
     * UI Components
     */
    private AddressChooser dest = new AddressChooser();
    private TextField msg       = new TextField(18);
    private Button go           = new Button("GO!");
    private Button send         = new Button("Send CLONE!");
    private Button close        = new Button("CLOSE");

    /*
     * Constructs the dialog window
     * @param aglet The aglet the user interacts with.
     */
    MyDialog(HelloAglet aglet) {
        this.aglet = aglet;
        layoutComponents();
        
        addWindowListener(this);
        go.addActionListener(this);
        send.addActionListener(this);
        close.addActionListener(this);
    }

    /*
     * Layouts all components
     */
    private void layoutComponents() {
        msg.setText(aglet.message);

        // Layouts components
        GridBagLayout grid = new GridBagLayout();
        GridBagConstraints cns = new GridBagConstraints();
        setLayout(grid);

        cns.weightx = 0.5;
        cns.ipadx = cns.ipady = 5;
        cns.fill = GridBagConstraints.HORIZONTAL;
        cns.insets = new Insets(5,5,5,5);

        cns.weightx = 1.0;
        cns.gridwidth = GridBagConstraints.REMAINDER;
        grid.setConstraints(dest, cns);
        add(dest);

        cns.gridwidth = GridBagConstraints.REMAINDER;
        cns.fill = GridBagConstraints.BOTH;
        cns.weightx = 1.0;
        cns.weighty = 1.0;
        cns.gridheight = 2;
        grid.setConstraints(msg, cns);
        add(msg);

        cns.weighty = 0.0;
        cns.fill = GridBagConstraints.NONE;
        cns.gridheight = 1;

        Panel p = new Panel();

        grid.setConstraints(p, cns);
        add(p);
        p.setLayout(new FlowLayout());
        p.add(go);
        p.add(send);
        p.add(close);
    }

    
    /**
     * Handles the action event
     * @param ae the event to be handled
     */
    public void actionPerformed(ActionEvent ae){
        // execute "GO!" command
        if("GO!".equals(ae.getActionCommand())){
            aglet.setMessage(msg.getText());
            try{
                AgletProxy p = aglet.getProxy();
                p.sendOnewayMessage(new Message("startTrip", dest.getAddress()));
            }catch(Exception e) {
                e.printStackTrace();
            }
        }
        
        // execute "Send CLONE!" command
        else if("Send CLONE!".equals(ae.getActionCommand())){
            aglet.message = msg.getText();
            try {
                 AgletProxy p = (AgletProxy)aglet.clone();
                 p.sendOnewayMessage(new Message("startTrip", dest.getAddress()));
            } catch (Exception e) {
                 e.printStackTrace();
            }
        }
        
        // execute "CLOSE" command
        else if("CLOSE".equals(ae.getActionCommand())){
            setVisible(false);
        }
    }

    /**
     * Handles the window event
     * @param we the event to be handled
     */

     public void windowClosing(WindowEvent we){
        dispose();
     }

     public void windowOpened(WindowEvent we){
     }

     public void windowIconified(WindowEvent we){
     }

     public void windowDeiconified(WindowEvent we){
     }

     public void windowClosed(WindowEvent we){
     }

     public void windowActivated(WindowEvent we){
     }

     public void windowDeactivated(WindowEvent we){
     }
}
